#include "be_command_system.h"

BeCommandSystem* BeCommandSystem::Instance () 
{
	static BeCommandSystem t;
	return &t;
}

BeCommandSystem::BeCommandSystem()
{
	settings = Settings::Instance();
// 	registerCmd("quit", &BeCommandSystem::quit);
// 	registerCmd("quit", &Basescene::quit);

	registerCmd("settings_saveprofile", &Settings::saveProfile);
	registerCmd("settings_increase", &Settings::increaseCVar);
	registerCmd("settings_decrease", &Settings::decreaseCVar);
}

void BeCommandSystem::registerCmd(const std::string& name, void (BeCommandSystem::*pt2Func)())
{
	cmd* c = new cmd();
	c->commandtype		= T_COMMAND;
	c->argtype		= A_NOARG;
	c->commandsMember	= pt2Func;
	cmdlist[name]		= c;
}

void BeCommandSystem::registerCmd(const std::string& name, void (BeCommandSystem::*pt2Func)(int))
{
	cmd* c = new cmd();
	c->commandtype		= T_COMMAND;
	c->argtype		= A_INT;
	c->commandsMember_int	= pt2Func;
	cmdlist[name]		= c;
}

void BeCommandSystem::registerCmd(const std::string& name, void (Settings::*pt2Func)())
{
	cmd* c = new cmd();
	c->commandtype		= T_SETTINGS;
	c->argtype		= A_NOARG;
	c->settingsMember	= pt2Func;
	cmdlist[name]		= c;
}

void BeCommandSystem::registerCmd(const std::string& name, void (Settings::*pt2Func)(const std::string&))
{
	cmd* c = new cmd();
	c->commandtype		= T_SETTINGS;
	c->argtype		= A_STRING;
	c->settingsMember_string= pt2Func;
	cmdlist[name]		= c;
}

// execCmd, these need to be inherited
void BeCommandSystem::execCmd(const std::string& name)
{
	generalExecCmd(name);
}

void BeCommandSystem::execCmd(const std::string& name, const std::string& str)
{
	generalExecCmd(name, str);
}

void BeCommandSystem::execCmd(const std::string& name, int number)
{
	generalExecCmd(name, number);
}

void BeCommandSystem::generalExecCmd(const std::string& name)
{
	if ( cmdlist[name]->commandtype == T_COMMAND )
		(this->*cmdlist[name]->commandsMember)();
	else if ( cmdlist[name]->commandtype == T_SETTINGS )
		(settings->*cmdlist[name]->settingsMember)();
}

void BeCommandSystem::generalExecCmd(const std::string& name, const std::string& str)
{
	if ( cmdlist[name]->commandtype == T_SETTINGS )
		(settings->*cmdlist[name]->settingsMember_string)(str);
}

void BeCommandSystem::generalExecCmd(const std::string& name, int number)
{
	if ( cmdlist[name]->commandtype == T_COMMAND )
		(this->*cmdlist[name]->commandsMember_int)(number);
}


// public execCmd
void BeCommandSystem::execCmd(const cmdsettings& cmds)
{
	// first check if called function exists
	if ( cmdlist[cmds.name] )
	{
		// check if expected types match
		if ( cmdlist[cmds.name]->argtype == cmds.argtype )
		{
			if ( cmds.argtype == A_NOARG )
				execCmd(cmds.name);
			else if ( cmds.argtype == A_STRING )
				execCmd(cmds.name, cmds.args);
			else if ( cmds.argtype == A_INT )
				execCmd(cmds.name, (int)cmds.argnumber);
			else if ( cmds.argtype == A_FLOAT )
				execCmd(cmds.name, cmds.argfloat);
		}
		else
			std::cerr << "command '" << cmds.name << "'s args do not match: got " << cmds.argtype << " but expected " << cmdlist[cmds.name]->argtype << std::endl;
	}
// 	else
// 		cerr << "command '" << cmds.name << "' does not exist" << endl;
}

/*void BeCommandSystem::quit()
{
	SDL_Quit();
// 	exit(0);
}
*/

BeCommandSystem::~BeCommandSystem()
{
	for( cmdit = cmdlist.begin(); cmdit != cmdlist.end(); cmdit++ )
		delete cmdit->second;
}
